package moon.excel.bean;

import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.math.NumberUtils;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Sheet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import moon.excel.CellRegion;
import moon.excel.ExcelExportWrapper;
import moon.excel.ExcelFormula;
import moon.excel.util.ExcelUtil;
import moon.util.DateUtils;

public class SimpleBeanExcelExportWrapper {
	private Logger logger = LoggerFactory.getLogger(SimpleBeanExcelExportWrapper.class);
	private ExcelExportWrapper excelWrapper = null;
	private Map<String, Object> functions = new HashMap<String, Object>();
	private CellStyle headStyle = null;// 默认行表头样式

	/**
	 * 
	 * @param type
	 *            xlsx或xls
	 */
	public SimpleBeanExcelExportWrapper(String type) {
		excelWrapper = new ExcelExportWrapper(type);
		init();
	}

	/**
	 * 默认导出xlsx格式
	 */
	public SimpleBeanExcelExportWrapper() {
		excelWrapper = new ExcelExportWrapper("xlsx");
		init();
	}

	private void init() {
		addFunctions("date", new DateUtils());
		addFunctions("number", new NumberUtils());
		headStyle = excelWrapper.getDefaultCellStyle();
	}

	/**
	 * 导出List<javabean>为excel文件
	 * 
	 * @param list目标集合
	 * @param outputStream指向导出文件的输出流
	 * @throws UnsupportedEncodingException
	 */
	private Sheet buildSheet(ExcelSheet excelSheet) throws UnsupportedEncodingException {
		long begin = System.currentTimeMillis();
		// 创建sheet
		Sheet sheet = excelWrapper.buildSheet(excelSheet.getName());
		// 创建表头
		buildTableHead(sheet, excelSheet);
		// 填充数据
		fillData(sheet, excelSheet);
		// 创建表尾
		buildTableFoot(sheet, excelSheet);
		// 合并单元格
		excelWrapper.mergeRegion(excelSheet.getCellRegions(), sheet);
		logger.info("excel_buildSheet时间：" + (System.currentTimeMillis() - begin) + "ms");
		return sheet;
	}

	/**
	 * 获取bean数据
	 * 
	 * @param sheet
	 * 
	 * @param excelSheet
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	private void fillData(Sheet sheet, ExcelSheet excelSheet) throws UnsupportedEncodingException {
		Object[] attrNames = excelSheet.getAttrNames();
		List<? extends Object> list = excelSheet.getBeans();
		// 获取行数据
		for (int i = 0; i < list.size(); i++) {
			Object rowObj = list.get(i);
			Object[] rowdata = interceptorRowFill(rowObj, excelSheet);
			if (rowdata == null) {
				rowdata = new Object[excelSheet.getColumnCount()];
				for (int j = 0; j < excelSheet.getColumnCount(); j++) {
					Object o = ExcelUtil.parseAttr(rowObj, attrNames[j], functions);
					rowdata[j] = o;
				}
			}
			excelWrapper.paint(sheet, i + 1 + excelSheet.getHeadEndRowIndex(), 0, rowdata, null, excelSheet.getInfoFormats());
		}
	}

	@SuppressWarnings("unchecked")
	private Object[] interceptorRowFill(Object rowObj, ExcelSheet excelSheet) {
		Object[] os = null;
		try {
			if (excelSheet.getRowInfoFillInterceptor() != null) {
				os = excelSheet.getRowInfoFillInterceptor().handle(rowObj);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return os;
	}

	/**
	 * 创建表尾
	 * 
	 * @param sheet
	 * @param excelSheet
	 */
	private void buildTableFoot(Sheet sheet, ExcelSheet excelSheet) {
		Object[] footvs = excelSheet.getTablefoot();
		if (footvs == null) {
			return;
		}
		Object[] datas = new Object[footvs.length];
		int regionBeginColumnIndex = 0;// 收集可合并列，默认为空的列向前合并
		for (int i = 0; i < footvs.length; i++) {
			Object v = footvs[i];
			if (v instanceof ExcelFormula) {
				ExcelFormula temp = new ExcelFormula(((ExcelFormula) v).getName());
				if (ExcelFormula.NAME_SUM.equals(temp.getName())) {
					String col = ExcelUtil.excelColIndexToStr(i + 1);
					temp.setFormula("sum(" + col + "1:" + col + (excelSheet.getHeadEndRowIndex() + excelSheet.getBeans().size() + 1) + ")");
					v = temp;
				}
			}
			datas[i] = v;
			// 收集可合并列开始
			if (ExcelUtil.isNotBlank(v)) {
				if (i - regionBeginColumnIndex > 1 && i > 1) {
					excelSheet.getCellRegions().add(new CellRegion(excelSheet.getFootBeginRowIndex(), excelSheet.getFootBeginRowIndex(), regionBeginColumnIndex, i - 1));
				}
				regionBeginColumnIndex = i % (footvs.length - 1);
			} else {
				if (i == footvs.length - 1 && i > regionBeginColumnIndex) {
					excelSheet.getCellRegions().add(new CellRegion(excelSheet.getFootBeginRowIndex(), excelSheet.getFootBeginRowIndex(), regionBeginColumnIndex, i));
					regionBeginColumnIndex = 0;
				}
			}
			// 收集可合并列结束
		}
		excelWrapper.paint(sheet, excelSheet.getFootBeginRowIndex(), excelSheet.getColumnBeginIndex(), datas, null, excelSheet.getInfoFormats());
	}

	/**
	 * 导出excel
	 * 
	 * @param list
	 * @param outputStream
	 */
	public List<Sheet> exportExcel(List<ExcelSheet> list, OutputStream outputStream) {
		List<Sheet> sheets = new ArrayList<Sheet>();
		try {
			for (ExcelSheet es : list) {
				sheets.add(buildSheet(es));
			}
			excelWrapper.export(outputStream);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return sheets;
	}

	/***
	 * 导出excel
	 * 
	 * @param sheet
	 * @param outputStream
	 */
	public Sheet exportExcel(ExcelSheet sheet, OutputStream outputStream) {
		Sheet wsheet = null;
		try {
			wsheet = buildSheet(sheet);
			excelWrapper.export(outputStream);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return wsheet;
	}

	/**
	 * 建立表头
	 * 
	 * @param sheet
	 * @param es
	 */
	private void buildTableHead(Sheet sheet, ExcelSheet es) {
		List<String[]> tableHeads = es.getTableHeads();
		if (!tableHeads.isEmpty()) {
			int rowindex = es.getHeadBeginRowIndex();
			int regionBeginColumnIndex = 0;// 收集可合并列，默认为空的列向前合并
			for (String[] headrow : tableHeads) {
				excelWrapper.paint(sheet, rowindex, es.getColumnBeginIndex(), headrow, headStyle);
				for (int i = 0; i < headrow.length; i++) {
					String columnName = headrow[i];
					// 收集可合并列开始
					if (ExcelUtil.isNotBlank(columnName)) {
						if (i - regionBeginColumnIndex > 1 && i > 1) {
							es.getCellRegions().add(new CellRegion(rowindex, rowindex, regionBeginColumnIndex, i - 1));
						}
						regionBeginColumnIndex = i % (headrow.length - 1);
					} else {
						if (i == headrow.length - 1 && i > regionBeginColumnIndex) {
							es.getCellRegions().add(new CellRegion(rowindex, rowindex, regionBeginColumnIndex, i));
							regionBeginColumnIndex = 0;
						}
					}
					// 收集可合并列结束
				}
				rowindex++;
			}
		}
	}

	/***
	 * 添加函数类
	 * 
	 * @param name
	 *            名称
	 * @param cla
	 *            类型
	 */
	public void addFunctions(String name, Object cla) {
		functions.put(name, cla);
	}

	public void setHeadCellStyle(CellStyle cellStyle) {
		this.headStyle = cellStyle;
	}
}
